using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using WPFTemplateLib.WpfConverters.Core;
/*
 * 版本：2025年11月13日
 */
namespace WPFTemplateLib.WpfConverters
{
	/// <summary>
	/// [转换器] 对象转换为可空值类型。（By Copilot）
	/// 说明：当目标类型为 Nullable~T 时，尝试将输入对象转换为对应的可空类型；
	/// - 输入为 null 或空字符串时返回 null；
	/// - 若已是目标基础类型则包装为 Nullable~T 返回；
	/// - 支持基础数值类型、布尔、日期及枚举的字符串转换；
	/// - 转换失败返回 Binding.DoNothing。
	/// </summary>
	public class ObjectToNullableConverter : ValueConverterBase
	{
		public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
		{
			// 未设置值则不处理
			if (Equals(value, DependencyProperty.UnsetValue))
				return Binding.DoNothing;

			// 仅在目标为可空类型时处理
			if (!(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>)))
			{
				return value;
			}

			Type underlyingType = Nullable.GetUnderlyingType(targetType)!;

			// null 或 空字符串 -> null
			if (value is null)
				return null;
			if (value is string s && string.IsNullOrWhiteSpace(s))
				return null;

			// 已经是目标基础类型 -> 包装为 Nullable<T>
			if (underlyingType.IsInstanceOfType(value))
				return BoxToNullable(underlyingType, value);

			try
			{
				// 字符串到枚举
				if (underlyingType.IsEnum)
				{
					string str = value.ToString()!;
					object enumVal = Enum.Parse(underlyingType, str, true);
					return BoxToNullable(underlyingType, enumVal);
				}

				// 针对 bool 处理 "1"/"0" 等
				if (underlyingType == typeof(bool))
				{
					if (value is string bs)
					{
						if (bool.TryParse(bs, out bool b)) return BoxToNullable(underlyingType, b);
						if (int.TryParse(bs, NumberStyles.Integer, culture, out int bi)) return BoxToNullable(underlyingType, bi != 0);
					}
					bool bv = System.Convert.ToBoolean(value, culture);
					return BoxToNullable(underlyingType, bv);
				}

				// 其它基础类型交给 ChangeType
				object converted = System.Convert.ChangeType(value, underlyingType, culture);
				return BoxToNullable(underlyingType, converted);
			}
			catch
			{
				return Binding.DoNothing;
			}
		}

		private static object BoxToNullable(Type underlyingType, object value)
		{
			Type nullableType = typeof(Nullable<>).MakeGenericType(underlyingType);
			return Activator.CreateInstance(nullableType, value);
		}
	}
}
